package abel.wlmr.model.unit;

import abel.util.StdBcdNumber;
import abel.wlmr.model.WlmrBaseUnit;
import abel.wlmr.model.WlmrException;
import abel.wlmr.model.type.MeterStatus1Field;
import abel.wlmr.model.type.MeterStatus2Field;
import abel.wlmr.model.type.MeterStatus3Field;
import io.netty.buffer.ByteBuf;

/**
 * 数据内容 数据格式 单位 字节数
 * 终端抄表时间 见附录 C.15 分时日月年 5
 * 水表运行状态字变位标志 1 BS16 2
 * 水表运行状态字变位标志 2 BS16 2
 * 水表运行状态字变位标志 3 BS16 2
 * 水表运行状态字变位标志 4 BS16 2
 * 水表运行状态字 1 BS16 2
 * 水表运行状态字 2 BS16 2
 * 水表运行状态字 3 BS16 2
 * 水表运行状态字 4 BS16 2
 * 
 * @author Abel
 *
 */
public class AfnFirstF402Unit extends WlmrBaseUnit {

    private static final short FIXED_LENGTH = 5 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2;

    /** 终端抄表时间 见附录 C.15 分时日月年 5 */
    private StdBcdNumber readingTime;

    private int change1;
    private int change2;
    private int change3;
    private int change4;

    /**
     * 脉冲计数
     * 异常（0-
     * 正常， 1-
     * 异常）
     * 直读异常
     * （0 正常/1
     * 异常）
     * 备用
     * 流量传感器状态
     * （00 正常/01 超上限）
     * 10 超下限 11 断线）
     * 压力传感器状态
     * （00 正常/01 超上限）
     * 10 超下限 11 断线）
     */
    private MeterStatus1Field status1 = new MeterStatus1Field();

    /**
     * 备用 备用
     * 电池 5 欠压
     * （0-正常， 1-
     * 异常）
     * 电池 4 欠压
     * （0-正常， 1-
     * 异常）
     * 电池 3 欠压
     * （0-正常， 1-
     * 异常）
     * 电池 2 欠压
     * （0-正常， 1-
     * 异常）
     * 电池 1 欠压
     * （0-正常， 1-
     * 异常）
     * 时钟电池
     * （0 正常/1 欠
     * 压）
     */
    private MeterStatus2Field status2 = new MeterStatus2Field();

    /**
     * 强磁检测
     * （0 正常/1 攻
     * 击）
     * 无线模块
     * （0 正常/1 异
     * 常）
     * 数据校验
     * （0 正常/1 异
     * 常）
     * 存储器状态（0
     * 正常/1 异常）
     */
    private MeterStatus3Field status3 = new MeterStatus3Field();

    private int status4;

    public AfnFirstF402Unit() {
        super();
    }

    public AfnFirstF402Unit(short guessedLen) {
        super(guessedLen);
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#appendBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public ByteBuf appendBuf(ByteBuf buf) {
        if (readingTime == null || readingTime.length() != 5) {
            throw new IllegalArgumentException("readingTime should be 5 bytes long");
        }

        buf.writeBytes(readingTime.toBytes());

        buf.writeShortLE(change1);
        buf.writeShortLE(change2);
        buf.writeShortLE(change3);
        buf.writeShortLE(change4);

        buf.writeShortLE(status1.getValue());
        buf.writeShortLE(status2.getValue());
        buf.writeShortLE(status3.getValue());
        buf.writeShortLE(status4);

        return buf;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#parseBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public int parseBuf(ByteBuf buf) throws WlmrException {
        if (checkBuffer(buf) < 0) {
            return -1;
        }

        readingTime = new StdBcdNumber();
        readingTime.populateBytes(buf, 5);

        change1 = buf.readShortLE();
        change2 = buf.readShortLE();
        change3 = buf.readShortLE();
        change4 = buf.readShortLE();

        status1 = new MeterStatus1Field();
        status1.parseValue(buf.readShortLE());
        status2 = new MeterStatus2Field();
        status2.parseValue(buf.readShortLE());
        status3 = new MeterStatus3Field();
        status3.parseValue(buf.readShortLE());
        status4 = buf.readShortLE();

        return FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.WlmrDataPart#getMinLength()
     */
    @Override
    public int getMinLength() {
        return FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.WlmrDataPart#getFinalLen()
     */
    @Override
    public short getFinalLen() {
        return FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return String.format(
            "{readingTime:%s, change1:%s, change2:%s, change3:%s, change4:%s, status1:%s, status2:%s, status3:%s, status4:%s}",
            readingTime, change1, change2, change3, change4, status1, status2, status3, status4);
    }

    /**
     * @return the change1
     */
    public int getChange1() {
        return change1;
    }

    /**
     * @param change1
     *            the change1 to set
     */
    public void setChange1(int change1) {
        this.change1 = change1;
    }

    /**
     * @return the change2
     */
    public int getChange2() {
        return change2;
    }

    /**
     * @param change2
     *            the change2 to set
     */
    public void setChange2(int change2) {
        this.change2 = change2;
    }

    /**
     * @return the change3
     */
    public int getChange3() {
        return change3;
    }

    /**
     * @param change3
     *            the change3 to set
     */
    public void setChange3(int change3) {
        this.change3 = change3;
    }

    /**
     * @return the change4
     */
    public int getChange4() {
        return change4;
    }

    /**
     * @param change4
     *            the change4 to set
     */
    public void setChange4(int change4) {
        this.change4 = change4;
    }

    /**
     * 终端抄表时间 见附录 C.15 分时日月年 5
     * 
     * @return the readingTime
     */
    public StdBcdNumber getReadingTime() {
        return readingTime;
    }

    /**
     * 终端抄表时间 见附录 C.15 分时日月年 5
     * 
     * @param readingTime
     *            the readingTime to set
     */
    public void setReadingTime(StdBcdNumber readingTime) {
        if (readingTime == null || readingTime.length() != 5) {
            throw new IllegalArgumentException("readingTime should be 5 bytes long");
        }

        this.readingTime = readingTime;
    }

    /**
     * @return the status1
     */
    public MeterStatus1Field getStatus1() {
        return status1;
    }

    /**
     * @param status1
     *            the status1 to set
     */
    public void setStatus1(MeterStatus1Field status1) {
        if (status1 == null) {
            throw new IllegalArgumentException("status1 can't be null");
        }
        this.status1 = status1;
    }

    /**
     * @return the status2
     */
    public MeterStatus2Field getStatus2() {
        return status2;
    }

    /**
     * @param status2
     *            the status2 to set
     */
    public void setStatus2(MeterStatus2Field status2) {
        if (status2 == null) {
            throw new IllegalArgumentException("status2 can't be null");
        }
        this.status2 = status2;
    }

    /**
     * @return the status3
     */
    public MeterStatus3Field getStatus3() {
        return status3;
    }

    /**
     * @param status3
     *            the status3 to set
     */
    public void setStatus3(MeterStatus3Field status3) {
        if (status3 == null) {
            throw new IllegalArgumentException("status3 can't be null");
        }
        this.status3 = status3;
    }

    /**
     * @return the status4
     */
    public int getStatus4() {
        return status4;
    }

    /**
     * @param status4
     *            the status4 to set
     */
    public void setStatus4(int status4) {
        this.status4 = status4;
    }
}
